// Licensed under GNU GPL V2.
// http://www.codeplex.com/WSSListConfigurator/
// (c) 2007 by Daniel Bedarf

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WSS3ListConfigurator
{
    public partial class frmMain : Form
    {

        #region Constructors
        public frmMain()
        {
            InitializeComponent();
        }
        #endregion

        #region Members
        Microsoft.SharePoint.SPSite _spsite;
        Microsoft.SharePoint.SPWeb _spweb;
        Microsoft.SharePoint.SPList _splist;
        Microsoft.SharePoint.SPField _spfield;
        #endregion

        #region Menues and Infrastructures
        
        private void frmMain_Load(object sender, EventArgs e)
        {
            this.Text = String.Format("{0} {1}", Application.ProductName, Application.ProductVersion);
            this.cmdProjectHome.Text = Properties.Settings.Default.ProjectURL;
            
            //Load possible EventTypes
            cboListEventType.Items.Clear();
            foreach (string eventType in Enum.GetNames(typeof(Microsoft.SharePoint.SPEventReceiverType)))
            {
                cboListEventType.Items.Add(eventType);
            }
            if (cboListEventType.Items.Count > 0) cboListEventType.SelectedIndex = 0;
            CheckAdvancedMode(sender, e);
        }

        private void ShowAboutDialog(object sender, EventArgs e)
        {
            frmAbout frm = new frmAbout();
            frm.ShowDialog(this);
        }

        private void OpenWebInBrowser(object sender, EventArgs e)
        {
            try
            {
                System.Diagnostics.Process.Start(txtWebURL.Text);
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void ShowBugManagement(object sender, EventArgs e)
        {
            try
            {
                System.Diagnostics.Process.Start(Properties.Settings.Default.BugTrackerURL);
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void ShowLicense(object sender, EventArgs e)
        {
            ShowLicenseFromLink(sender, null);
        }

        private void ShowProjectHome(object sender, LinkLabelLinkClickedEventArgs e)
        {
            try
            {
                System.Diagnostics.Process.Start(Properties.Settings.Default.ProjectURL);
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void ShowLicenseFromLink(object sender, LinkLabelLinkClickedEventArgs e)
        {
            ShowLicense(sender, null);
        }

        private void CheckAdvancedMode(object sender, EventArgs e)
        {
            if (mnuAdvancedMode.Checked)
            {
                if (!tabCtrlField.TabPages.Contains(tabPageFieldAdvanced)) tabCtrlField.TabPages.Add(tabPageFieldAdvanced);
                if (!tabCtrlList.TabPages.Contains(tabPageListAdvanced)) tabCtrlList.TabPages.Add(tabPageListAdvanced);
                if (!tabCtrlWeb.TabPages.Contains(tabPageWebAdvanced)) tabCtrlWeb.TabPages.Add(tabPageWebAdvanced);
            }
            else
            {
                if (tabCtrlField.TabPages.Contains(tabPageFieldAdvanced)) tabCtrlField.TabPages.Remove(tabPageFieldAdvanced);
                if (tabCtrlList.TabPages.Contains(tabPageListAdvanced)) tabCtrlList.TabPages.Remove(tabPageListAdvanced);
                if (tabCtrlWeb.TabPages.Contains(tabPageWebAdvanced)) tabCtrlWeb.TabPages.Remove(tabPageWebAdvanced);
            }//end if else checked
        }

        #endregion

        #region Web

        /// <summary>
        /// Open a Conncetion to a WSS-Web and Fill "Lists" - list
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmdConnectWeb_Click(object sender, EventArgs e)
        {
            try
            {
                _spsite = new Microsoft.SharePoint.SPSite(txtWebURL.Text);
                _spweb = _spsite.OpenWeb();
                lstLists.Items.Clear();
                StatusInit(_spweb.Lists.Count, "Read Lists");
                foreach (Microsoft.SharePoint.SPList li in _spweb.Lists)
                {
                    lstLists.Items.Add(li.Title);
                    StatusNext();
                }
                StatusReset();
                propGridWeb.SelectedObject = _spweb;
                ReadBasicWebPropertys();
                ShowWebPropertys();
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        /// <summary>
        /// Read all settings of the spweb which are supported in non advanced mode
        /// </summary>
        private void ReadBasicWebPropertys()
        {
            if (_spweb != null)
            {
                chkWebAllowUnsafeUpdates.Checked = _spweb.AllowUnsafeUpdates;
            }//end if splist!=null
        }

        private void cmdSaveWebChanges_Click(object sender, EventArgs e)
        {
            try
            {
                _spweb.Update();
                ShowInformation("Web updated");
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void chkWebAllowUnsafeUpdates_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                _spweb.AllowUnsafeUpdates = chkWebAllowUnsafeUpdates.Checked;
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

         #endregion

        #region Lists

        private void lstLists_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                lstFields.Items.Clear();
                _splist = _spweb.Lists[lstLists.SelectedItem.ToString()];
                StatusInit(_splist.Fields.Count, "Read Fields");
                foreach (Microsoft.SharePoint.SPField fi in _splist.Fields)
                {
                    lstFields.Items.Add(fi.Title);
                    StatusNext();
                }
                StatusReset();
                propGridList.SelectedObject = _splist;
                ReadBasicListPropertys();
                ShowListPropertys();
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void cmdSaveListChanges_Click(object sender, EventArgs e)
        {
            try
            {
                _splist.Update();
                ShowInformation("List updated");
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        #region BasicProps

        /// <summary>
        /// Sync Advanced - Page with basic settings
        /// </summary>
        /// <param name="s"></param>
        /// <param name="e"></param>
        private void propGridList_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            ReadBasicListPropertys();
        }
       
        /// <summary>
        /// Read all settings of the splist which are supported in non advanced mode
        /// </summary>
        private void ReadBasicListPropertys()
        {
            try
            {
                if (_splist != null)
                {
                    chkListAllowDelete.Checked = _splist.AllowDeletion;
                    chkListHidden.Checked = _splist.Hidden;
                    chkListAllowRequestAccess.Checked = _splist.RequestAccessEnabled;

                    lvwListCurrentEventHandler.Items.Clear();
                    foreach (Microsoft.SharePoint.SPEventReceiverDefinition rec in _splist.EventReceivers)
                    {
                        ListViewItem li = new ListViewItem();
                        li.Text = rec.Type.ToString();
                        li.SubItems.Add(rec.Assembly);
                        li.SubItems.Add(rec.Class);
                        li.Tag = rec;
                        lvwListCurrentEventHandler.Items.Add(li);
                    }

                    if (lvwListCurrentEventHandler.Items.Count > 0)
                    {
                        if (tabCtrlList.TabPages.Contains(tabPageListCurrentEventHandler) == false)
                            tabCtrlList.TabPages.Add(tabPageListCurrentEventHandler);
                    }
                    else
                    {
                        if (tabCtrlList.TabPages.Contains(tabPageListCurrentEventHandler) == true)
                            tabCtrlList.TabPages.Remove(tabPageListCurrentEventHandler);
                    }

                }//end if splist!=null

            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void chkListHidden_CheckedChanged(object sender, EventArgs e)
        {
            _splist.Hidden = chkListHidden.Checked;
        }

        private void chkListAllowRequestAccess_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                if(_splist.RequestAccessEnabled!=chkListAllowRequestAccess.Checked)
                    _splist.RequestAccessEnabled = chkListAllowRequestAccess.Checked;
            }
            catch (Exception ex)
            {
                chkListAllowRequestAccess.Checked = _splist.RequestAccessEnabled;
                HandleError(ex);
            }
        }

        private void chkListAllowDelete_CheckedChanged(object sender, EventArgs e)
        {
            _splist.AllowDeletion = chkListAllowDelete.Checked;
        }

        #endregion

        /// <summary>
        /// Open FileDialog and Load Assembly for Eventhandler
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmdListBrowseAssembly_Click(object sender, EventArgs e)
        {
            try
            {
                if (ofdAssembly.ShowDialog() == DialogResult.OK)
                {
                    cboListEventClass.Items.Clear();
                    txtListEventAssembly.Text = "";

                    System.Reflection.Assembly asm = System.Reflection.Assembly.LoadFile(ofdAssembly.FileName);
                    txtListEventAssembly.Text = asm.FullName;
                    foreach (System.Type t in asm.GetExportedTypes())
                    {
                        if (t.IsClass)
                            if
                            (
                                chkListEventShowOnlySPItemEventReceiver.Checked==false ||
                                t.IsSubclassOf(typeof(Microsoft.SharePoint.SPItemEventReceiver))
                            )
                            cboListEventClass.Items.Add(t.FullName);
                    }
                    if (!asm.GlobalAssemblyCache)
                    {
                        ShowInformation("You have to put your Assembly to the GAC before press Add!");
                    }

                    if (cboListEventClass.Items.Count > 0)
                    {
                        cboListEventClass.SelectedIndex = 0;
                        cmdListEventHandler_Add.Enabled = true;
                    }
                    else cmdListEventHandler_Add.Enabled = false;

                }//endif Assembyl selected

            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void cmdListItemEventHandler_Add_Click(object sender, EventArgs e)
        {
            try
            {
                _splist.EventReceivers.Add(
                    (Microsoft.SharePoint.SPEventReceiverType)Enum.Parse(
                    typeof(Microsoft.SharePoint.SPEventReceiverType),
                    cboListEventType.Text),
                    txtListEventAssembly.Text,
                    cboListEventClass.SelectedItem.ToString());
                ShowInformation("EventReceiver Added\nRemember: save changes is not necessary.");
                ReadBasicListPropertys();
            }
            catch (Exception ex)
            {
                chkListAllowRequestAccess.Checked = _splist.RequestAccessEnabled;
                HandleError(ex);
            }
        }

        private void cmdListEventHandler_Delete_Click(object sender, EventArgs e)
        {
            try
            {
                if (lvwListCurrentEventHandler.SelectedItems.Count > 0)
                {
                    if (!(lvwListCurrentEventHandler.SelectedItems[0].Tag is Microsoft.SharePoint.SPEventReceiverDefinition))
                        throw new Exception("Inavlid Type in Element.Tag");
                    Microsoft.SharePoint.SPEventReceiverDefinition rec = (Microsoft.SharePoint.SPEventReceiverDefinition)lvwListCurrentEventHandler.SelectedItems[0].Tag;
                    if (MessageBox.Show("Are you sure you want to remove this handler?", "Remove Eventhandler", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    {
                        rec.Delete();
                        ReadBasicListPropertys();
                    }
                    else
                    {
                        //canceld
                    }

                }//end if SelectedItems.Count>0
                else
                {
                    ShowInformation("Please select a handler to delete.");
                }//end if else SelectedItems.Count>0

            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void chkListEventShowOnlySPItemEventReceiver_CheckedChanged(object sender, EventArgs e)
        {
            ShowInformation("Please open the Assembly again to take affect");
        }

        #endregion Lists

        #region Field

        private void lstFields_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                _spfield = _spweb.Lists[lstLists.SelectedItem.ToString()].Fields[lstFields.SelectedItem.ToString()];

                if (_spfield != null)
                {

                    ReadBasicFieldPropertys();

                    //Show/Hide the Lookup COnfigurator
                    if(_spfield is Microsoft.SharePoint.SPFieldLookup)
                    {
                        Microsoft.SharePoint.SPFieldLookup _tmpFieldLookup=(Microsoft.SharePoint.SPFieldLookup)_spfield;
                        if(tabCtrlField.TabPages.Contains(tabPageFieldLookup)==false)
                            tabCtrlField.TabPages.Add(tabPageFieldLookup);
                        //Fill Lookup - Combos
                        cboFieldLookupWeb.Items.Clear();
                        int index = -1;
                        foreach (Microsoft.SharePoint.SPWeb web in _spsite.AllWebs)
                        {
                            int tmpIndex=cboFieldLookupWeb.Items.Add(web);
                            if (web.ID == _tmpFieldLookup.LookupWebId) index = tmpIndex;
                            
                        }//end foreach web
                        cboFieldLookupWeb.SelectedIndex = index;
                        foreach (Microsoft.SharePoint.SPList list in cboFieldLookupList.Items)
                        {
                            if (_tmpFieldLookup.LookupList.Contains(list.ID.ToString()))
                            {
                                cboFieldLookupList.SelectedIndex = cboFieldLookupList.Items.IndexOf(list);
                                break;
                            }
                        }//end foreach list in cboFieldLookupList

                        cboFieldLookupField.SelectedIndex = cboFieldLookupField.Items.IndexOf(_tmpFieldLookup.LookupField);

                    }//end if Lookup
                    else
                    {
                        if (tabCtrlField.TabPages.Contains(tabPageFieldLookup) == true)
                            tabCtrlField.TabPages.Remove(tabPageFieldLookup);
                    }
                    ShowFieldPropertys();
                }//end if _spfield!=null

            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void cboFieldLookupWeb_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (cboFieldLookupWeb.SelectedItem is Microsoft.SharePoint.SPWeb)
                {
                    Microsoft.SharePoint.SPWeb web = (Microsoft.SharePoint.SPWeb)cboFieldLookupWeb.SelectedItem;
                    cboFieldLookupList.Items.Clear();
                    foreach (Microsoft.SharePoint.SPList list in web.Lists)
                    {
                        cboFieldLookupList.Items.Add(list);
                    }
                }//end if SPWeb

            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void cboFieldLookupList_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (cboFieldLookupList.SelectedItem is Microsoft.SharePoint.SPList)
                {
                    Microsoft.SharePoint.SPList list = (Microsoft.SharePoint.SPList)cboFieldLookupList.SelectedItem;
                    cboFieldLookupField.Items.Clear();
                    foreach (Microsoft.SharePoint.SPField field in list.Fields)
                    {
                        cboFieldLookupField.Items.Add(field.InternalName);
                    }
                }//end if SPList
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        private void cboFieldLookupField_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (_spfield is Microsoft.SharePoint.SPFieldLookup)
                {
                    Microsoft.SharePoint.SPFieldLookup tmpLookup = (Microsoft.SharePoint.SPFieldLookup)_spfield;
                    if (!(cboFieldLookupList.SelectedItem is Microsoft.SharePoint.SPList)) throw new Exception("Combo for LookupFieldLists does not contains SPList - Items");
                    Microsoft.SharePoint.SPList tmpLookupList = (Microsoft.SharePoint.SPList)cboFieldLookupList.SelectedItem;
                    if (!(cboFieldLookupWeb.SelectedItem is Microsoft.SharePoint.SPWeb)) throw new Exception("Combo for LookupFieldWebs does not contains SPWeb - Items");
                    Microsoft.SharePoint.SPWeb tmpLookupWeb = (Microsoft.SharePoint.SPWeb)cboFieldLookupWeb.SelectedItem;

                    if (
                        string.IsNullOrEmpty(cboFieldLookupField.SelectedText)==false 
                        &&
                            (
                                tmpLookup.LookupField != cboFieldLookupField.SelectedText
                                ||
                                tmpLookup.LookupList != tmpLookupList.ID.ToString("B") 
                                ||
                                tmpLookup.LookupWebId == tmpLookupWeb.ID
                            )
                        )
                    {
                        tmpLookup.LookupWebId = tmpLookupWeb.ID;

                        //It's not allowed to call
                        //tmpLookup.LookupList = tmpLookupList.ID.ToString("B") ;
                        //tmpLookup.SetCustomProperty("List", tmpLookupList.ID.ToString("B"));
                        System.Type t = tmpLookup.GetType();
                        System.Reflection.MethodInfo mi = 
                            t.BaseType.GetMethod("SetFieldAttributeValue", 
                            System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
                        if (mi!=null)
                        {
                            mi.Invoke(tmpLookup, new object[] { "List", tmpLookupList.ID.ToString("B") });
                        }//MI found?
                        tmpLookup.LookupField = cboFieldLookupField.SelectedText;
                    }//end if some Changes?
                }//endif _spField is Lookup

            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        #region BasicProps

        /// <summary>
        /// Read the Informations which are Displayed in "Basic"-Tab from SPField (_spfield)
        /// </summary>
        private void ReadBasicFieldPropertys()
        {
            if (_spfield != null)
            {

                propGridField.SelectedObject = _spfield;

                chkFieldRequired.Checked = _spfield.Required;
                chkFieldReadOnly.Checked = _spfield.ReadOnlyField;
                chkFieldHidden.Checked = _spfield.Hidden;
                chkFieldCanDeleted.Checked = GetValue(_spfield.AllowDeletion, true);

                chkFieldShowInNewForm.Checked = GetValue(_spfield.ShowInNewForm, true);
                chkFieldShowInEditForm.Checked = GetValue(_spfield.ShowInEditForm, true);
                chkFieldShowInDisplayForm.Checked = GetValue(_spfield.ShowInDisplayForm, true);
                chkFieldShowInViewForm.Checked = GetValue(_spfield.ShowInViewForms, true);
                chkFieldShowInListSettings.Checked = GetValue(_spfield.ShowInListSettings, true);
            }

        }

        private void propGridField_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            ReadBasicFieldPropertys();
        }

        private void chkFieldShowInNewForm_CheckedChanged(object sender, EventArgs e)
        {
            if(GetValue(_spfield.ShowInNewForm,true)!= chkFieldShowInNewForm.Checked)
                _spfield.ShowInNewForm = chkFieldShowInNewForm.Checked;
        }

        private void chkFieldShowInEditForm_CheckedChanged(object sender, EventArgs e)
        {
            if (GetValue(_spfield.ShowInEditForm, true) != chkFieldShowInEditForm.Checked)
                _spfield.ShowInEditForm = chkFieldShowInEditForm.Checked;
        }

        private void chkFieldShowInDisplayForm_CheckedChanged(object sender, EventArgs e)
        {
            if (GetValue(_spfield.ShowInDisplayForm, true) != chkFieldShowInDisplayForm.Checked)
                _spfield.ShowInDisplayForm = chkFieldShowInDisplayForm.Checked;
        }

        private void chkFieldShowInViewForm_CheckedChanged(object sender, EventArgs e)
        {
            if (GetValue(_spfield.ShowInViewForms, true) != chkFieldShowInViewForm.Checked)
                _spfield.ShowInViewForms = chkFieldShowInViewForm.Checked;
        }

        private void chkFieldShowInListSettings_CheckedChanged(object sender, EventArgs e)
        {
            if (GetValue(_spfield.ShowInListSettings, true) != chkFieldShowInListSettings.Checked)
                _spfield.ShowInListSettings = chkFieldShowInListSettings.Checked;
        }

        private void chkFieldRequired_CheckedChanged(object sender, EventArgs e)
        {
            if (GetValue(_spfield.Required, true) != chkFieldRequired.Checked)
                _spfield.Required = chkFieldRequired.Checked;
        }

        private void chkFieldReadOnly_CheckedChanged(object sender, EventArgs e)
        {
            if (GetValue(_spfield.ReadOnlyField, true) != chkFieldReadOnly.Checked)
                _spfield.ReadOnlyField = chkFieldReadOnly.Checked;
        }

        private void chkFieldHidden_CheckedChanged(object sender, EventArgs e)
        {
            if (GetValue(_spfield.Hidden, true) != chkFieldHidden.Checked)
                _spfield.Hidden = chkFieldHidden.Checked;
        }

        private void chkFieldCanDeleted_CheckedChanged(object sender, EventArgs e)
        {
            if (GetValue(_spfield.AllowDeletion, true) != chkFieldCanDeleted.Checked)
                _spfield.AllowDeletion = chkFieldCanDeleted.Checked;

        }
        #endregion

        private void cmdSaveField_Click(object sender, EventArgs e)
        {
            try
            {
                _spfield.Update();
                ShowInformation("Changes saved");
            }
            catch (Exception ex)
            {
                HandleError(ex);
            }
        }

        #endregion

        #region Helper

        /// <summary>
        /// Get a Value from a possible NULL - Property
        /// </summary>
        /// <param name="value"></param>
        /// <param name="Default"></param>
        /// <returns></returns>
        bool GetValue(bool? value, bool Default)
        {
            if (value != null)
                return (bool)value;
            else
                return Default;
        }

        /// <summary>
        /// Handles Errors and Display a ErrorMessage
        /// </summary>
        /// <param name="ex"></param>
        private void HandleError(Exception ex)
        {
            MessageBox.Show(ex.Message, "Information", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        }

        /// <summary>
        /// Show a Information - Dialog
        /// </summary>
        /// <param name="Message"></param>
        private void ShowInformation(string Message)
        {
            MessageBox.Show(Message, "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        /// <summary>
        /// Show a Progressbar and change the Coursor to Wait
        /// </summary>
        /// <param name="Maximum"></param>
        /// <param name="Message"></param>
        private void StatusInit(int Maximum, string Message)
        {
            prgStatus.Visible = true;
            lblCurrentAction.Text = Message;
            lblCurrentAction.Visible = true;
            prgStatus.Value = 0;
            prgStatus.Maximum = Maximum;
            this.Cursor = Cursors.WaitCursor;
        }

        /// <summary>
        /// Update the Value in the Progressbar
        /// </summary>
        private void StatusNext()
        {
            if (prgStatus.Maximum >= prgStatus.Value + 1)
                prgStatus.Value += 1;
        }

        /// <summary>
        /// Hide the Progressabr and change the cursor to default
        /// </summary>
        private void StatusReset()
        {
            prgStatus.Visible = false;
            lblCurrentAction.Visible = false;
            this.Cursor = Cursors.Default;
        }

        /// <summary>
        /// Show the Propertypages for Web-Settings
        /// </summary>
        private void ShowWebPropertys()
        {
            fraMain.Visible = false;
            fraListPropertys.Visible = false;
            fraFieldPropertys.Visible = false;
            fraWebPropertys.Visible = true;
        }

        /// <summary>
        /// Show the Propertypages for Field-Setttings
        /// </summary>
        private void ShowFieldPropertys()
        {
            fraMain.Visible = false;
            fraFieldPropertys.Visible = true;
            fraListPropertys.Visible = false;
            fraWebPropertys.Visible = false;
        }

        /// <summary>
        /// Show the Propertypages for List-Settings
        /// </summary>
        private void ShowListPropertys()
        {
            fraMain.Visible = false;
            fraListPropertys.Visible = true;
            fraFieldPropertys.Visible = false;
            fraWebPropertys.Visible = false;
        }

        #endregion

    }
}